package org.eclipse.mylyn.rememberthemilk.core;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.mylyn.rememberthemilk.core.RTMCorePlugin;
import org.eclipse.mylyn.rememberthemilk.core.RTMRepositoryConnector;
import org.eclipse.mylyn.rememberthemilk.core.RTMTaskDataHandler;
import org.eclipse.mylyn.rememberthemilk.core.client.RTMClient;
import org.eclipse.mylyn.rememberthemilk.core.client.RTMClientManager;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.mdt.rtm.data.RtmData;
import com.mdt.rtm.data.RtmTask;
import com.mdt.rtm.data.RtmTaskNote;
import com.mdt.rtm.data.RtmTaskNotes;
import com.mdt.rtm.data.RtmTaskSeries;

public class RTMDataHandlerTest extends BaseRtmTests {
	private Mockery context = new Mockery() {{
		setImposteriser(ClassImposteriser.INSTANCE);
	}};
	private RTMTaskDataHandler handler;
	private TaskRepository repository;
	
	@Before
	public void setUp() throws Exception {
		final RTMRepositoryConnector connector = context.mock(RTMRepositoryConnector.class);
		final RTMClientManager manager = context.mock(RTMClientManager.class);
		final RTMClient client = context.mock(RTMClient.class);
		final Map<String, String> listMap = new HashMap<String, String>();
		listMap.put("1", "test llist");
		context.checking(new Expectations() {{
			allowing (connector).getClientManager(); will(returnValue(manager));
			allowing (manager).getRepository(with(any(TaskRepository.class))); will(returnValue(client));
			allowing (client).getRTMListMap(); will(returnValue(listMap));
		}});
		handler = new RTMTaskDataHandler(connector);
		repository = createTaskRepository();
	}

	@After
	public void tearDown() throws Exception {
	}
	
	@Test
	public void testGetAttributeMapper() {
		TaskRepository repository = createTaskRepository();
		TaskAttributeMapper mapper = handler.getAttributeMapper(repository);
		assertNotNull(mapper);
	}
	
	@Test
	public void testIdMapping() throws Exception {
		RtmTask task = new RtmTask("3", null, 0, null, null, null, null, 0, null);
		RtmTaskSeries series = new RtmTaskSeries("2", null, null, null, null, task, "1");
		
		TaskData data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("incorrect list id", "1", getValue(data, "listId"));
		assertEquals("incorrect series id", "2", getValue(data, "seriesId"));
		assertEquals("incorrect task id", "3", getValue(data, "taskId"));
	}

	@Test
	public void testSummaryMapping() throws Exception {
		String nameValue = "Try out Remember The Milk";
		RtmTaskSeries series = new RtmTaskSeries("1", null, null, nameValue, null, null, "1");

		TaskData data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("Regular attribute name was wrong", nameValue, getValue(data, "name"));
	}
	
	@Test
	public void testCompletedDate() throws Exception {
		Date dateValue = RtmTask.parseDate("2009-05-11T00:10:05Z");
		RtmTask task = new RtmTask("1", null, 0, null, dateValue, null, null, 0, null);
		RtmTaskSeries series = createTaskSeries(task);

		TaskData data = handler.createTaskDataFromSeries(series, repository);
		assertEquals("provided completed date was incorrect", Long.toString(dateValue.getTime()), getValue(data, "completedDate"));
		assertEquals("task was not marked as complete", "complete", getValue(data, "status"));
		
		task = new RtmTask("1", null, 0, null, null, null, null, 0, null);
		series = createTaskSeries(task);
		
		data = handler.createTaskDataFromSeries(series, repository);
		assertEquals("task was not marked as incomplete", "incomplete", getValue(data, "status"));
	}
	
	@Test
	public void testPriorityMapping() throws Exception {
		RtmTask task = new RtmTask("1", null, 0, null, null, null, RtmTask.Priority.High, 0, null);
		RtmTaskSeries series = createTaskSeries(task);
		
		TaskData data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("incorrect priority returned for high priority", "P1", getValue(data, "priority"));
		
		task = new RtmTask("1", null, 0, null, null, null, RtmTask.Priority.Medium, 0, null);
		series = createTaskSeries(task);
		
		data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("incorrect priority returned for medium priority", "P2", getValue(data, "priority"));
		
		task = new RtmTask("1", null, 0, null, null, null, RtmTask.Priority.Low, 0, null);
		series = createTaskSeries(task);
		
		data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("incorrect priority returned for low priority", "P4", getValue(data, "priority"));
		
		task = new RtmTask("1", null, 0, null, null, null, RtmTask.Priority.None, 0, null);
		series = createTaskSeries(task);
		
		data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("incorrect priority returned for no priority", "P3", getValue(data, "priority"));
	}
	
	@Test
	public void testCreatedDateMapping() throws Exception {
		Date dateValue = RtmTaskSeries.parseDate("2009-05-08T02:01:16Z");
		RtmTaskSeries series = new RtmTaskSeries("1", dateValue, null, null, null, null, "1");
		
		TaskData data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("Invalid date was returned", Long.toString(dateValue.getTime()), getValue(data, "createdDate"));
	}
	
	@Test
	public void testModifiedDateMapping() throws Exception {
		Date dateValue = RtmTaskSeries.parseDate("2009-06-14T23:21:23Z");
		RtmTaskSeries series = new RtmTaskSeries("1", null, dateValue, null, null, null, "1");
		
		TaskData data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("Invalid date was returned", Long.toString(dateValue.getTime()), getValue(data, "modifiedDate"));
	}
	
	@Test
	public void testDueDateMapping() throws Exception {
		Date dateValue = RtmTaskSeries.parseDate("2009-05-10T06:00:00Z");
		RtmTask task = new RtmTask("1", dateValue, 0, null, null, null, null, 0, null);
		RtmTaskSeries series = createTaskSeries(task);
		
		TaskData data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("Invalid Due date was returned", Long.toString(dateValue.getTime()), getValue(data, "dueDate"));
	}
	
	@Test
	public void testPostponedMapping() throws Exception {
		RtmTask task = new RtmTask("1", null, 0, null, null, null, null, 2, null);
		RtmTaskSeries series = createTaskSeries(task);
		
		TaskData data = handler.createTaskDataFromSeries(series, repository);
		
		assertEquals("Wrong number of postpones sent", "2", getValue(data, "postponed"));
	}

	private RtmTaskSeries createTaskSeries(RtmTask task) {
		return new RtmTaskSeries("1", null, null, null, null, task, "1");
	}
	
//	@Test
	public void testNoteMapping() throws Exception {
//		RtmTaskNote note = new RtmTaskNote("1", "title", "text");
//		List<RtmTaskNote> noteList = new ArrayList<RtmTaskNote>();
//		noteList.add(note);
//		RtmTaskNotes notes = new RtmTaskNotes(noteList);
//		RtmTaskSeries series = new RtmTaskSeries("1", null, null, null, null, null, notes, "1");
//		
//		TaskData data = handler.createTaskDataFromSeries(series, repository);
//		
//		List<TaskAttribute> attributes = data.getAttributeMapper().getAttributesByType(data, TaskAttribute.TYPE_COMMENT);
//		
//		assertEquals("title", attributes.get(0).getAttribute("title").getValue());
//		assertEquals("text", attributes.get(0).getAttribute("text").getValue());
//		assertEquals("1", attributes.get(0).getAttribute("id").getValue());
		
//		assertEquals()
	}

	private String getValue(TaskData data, String name) {
		return data.getRoot().getAttribute(name).getValue();
	}
}